/**
 * Copyright 厦门中软海晟信息技术有限公司 版权所有 违者必究 2019
 */
package com.opencvjava.piano.support;

import com.opencvjava.piano.Extract2;

import java.awt.Image;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import static com.opencvjava.piano.support.Unit.R;
import static com.opencvjava.piano.support.Unit.RR;

/**
 * @author : sunzb
 * @date: 2019/11/28
 */
public class UnitBuilder {

    private ImageInfo img;
    int rowIteNum;
    int colIteNum;
    byte[] data;

    public ImageInfo units() {
        int rowStart, rowEnd, colStart, colEnd, rowIndex, color, sum, avg, var, unitIndex;
        for (int j = 0; j < colIteNum; j++) {
            for (int i = 0; i < rowIteNum; i++) {
                rowStart = i * R;
                rowEnd = rowStart + R;
                colStart = j * R;
                colEnd = colStart + R;
                sum = 0;
                var = 0;
                List<Integer> unitData = new ArrayList<>();
                for (int row = rowStart; row < rowEnd; row++) {
                    rowIndex = row * img.getCols();
                    for (int col = colStart; col < colEnd; col++) {
                        color = data[rowIndex + col] & 0xff;
                        sum += color;
                        unitData.add(color);
                    }
                }
                avg = sum / RR;
                for (int temp : unitData) {
                    var += Math.pow(temp - avg, 2);
                }
                Unit unit = new Unit().setRowStart(rowStart).setColStart(colStart)
                        .setData(unitData).setAvg(avg).setVar(var)
                        .setImageInfo(img).setIndex(img.getUnits().size());
                img.getUnits().add(unit);
                if (var < 100) {
                    unit.setFill(true).setUsed(true);
                    img.getFillBlock().getUnits().add(unit);
                }
            }
        }
        return img;
    }

    public ImageInfo blocks() {
        for (Unit unit : img.getUnits()) {
            if (!unit.isUsed() && !unit.isFill()) {
                Block block = new Block();
                LinkedList<Unit> bfs = new LinkedList<>();
                bfs.push(unit);
                while (!bfs.isEmpty()) {
                    Unit pop = bfs.pop();
                    if (pop.isUsed()) continue;
                    if (pop.isFill()) continue;
                    block.getUnits().add(pop);
                    pop.setUsed(true);
                    int tIndex = pop.getIndex() - rowIteNum;
                    int bIndex = pop.getIndex() + rowIteNum;
                    int lIndex = pop.getIndex() - 1;
                    int rIndex = pop.getIndex() + 1;
                    if (tIndex > 0) bfs.push(img.getUnits().get(tIndex));
                    if (bIndex < img.getUnits().size()) bfs.push(img.getUnits().get(bIndex));
                    if (lIndex > 0) bfs.push(img.getUnits().get(lIndex));
                    if (rIndex < img.getUnits().size()) bfs.push(img.getUnits().get(rIndex));
                }
                if (block.getUnits().size() < 10) {
                    for (Unit unitIte : block.getUnits()) {
                        unitIte.setFill(true);
                        img.getFillBlock().getUnits().add(unitIte);
                    }
                } else {
                    img.getBlocks().add(block);
                }
            }
        }
        return img;
    }

    public UnitBuilder setImg(ImageInfo img) {
        this.img = img;
        rowIteNum = img.getRows() / R - 1;
        colIteNum = img.getCols() / R - 1;
        data = img.getData();
        return this;
    }

    public ImageInfo getImg() {
        return img;
    }
}
